﻿namespace MSSqlSchemaDoc.Core
{
    using System;
    using System.Collections.ObjectModel;
    using System.IO;

    using MSSqlSchemaDoc.Core.DataStructures;

    /// <summary>
    /// Provides the contract that scripting manager objects need to adhere to.
    /// Typically, each provider type will implement a provider specific scripting manager.
    /// </summary>
    public interface IScriptingManager
    {
        /// <summary>
        /// Fires whenever the scripting operation starts to script a new type of object.
        /// The "sender" object reference will be null.
        /// The event argument will be a string with the name of the type of object.
        /// </summary>
        event EventHandler<SimpleEventArgs<string>> BeginScriptingNewObjectType;

        /// <summary>
        /// Fires whenever the scripting operation completes scripting a type of object.
        /// The "sender" object reference will be null.
        /// The event argument will be a string with the name of the type of object.
        /// </summary>
        event EventHandler<SimpleEventArgs<string>> CompleteScriptingNewObjectType;

        /// <summary>
        /// Fires whenever the scripting operation starts to script an object.
        /// The "sender" object reference will be null.
        /// The event argument will be a string with the name of the object.
        /// </summary>
        event EventHandler<SimpleEventArgs<string>> BeginScriptingObject;

        /// <summary>
        /// Fires whenever the scripting operation completes the scripting of an object.
        /// The "sender" object will be a reference to the object that was just scripted.
        /// The event argument will be a string with the name of the bject.
        /// </summary>
        event EventHandler<SimpleEventArgs<string>> CompleteScriptingObject;

        /// <summary>
        /// Gets or sets a value indicating whether the generated Xml should be validated against the Xml Schemas.
        /// </summary>
        bool ValidateXml { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether to also script the documentation objects.
        /// </summary>
        bool IncludeDocumentationObjects { get; set; }

        /// <summary>
        /// Gets or sets the source folder for documentation.
        /// The documentation in the existing files will be carried over to the new objects.
        /// </summary>
        DirectoryInfo DocumentationSourceFolder { get; set; }

        /// <summary>
        /// Script a connection and save the results in files.
        /// In addition to the script being saved in a file, it is also possible to handle
        /// the "CompleteScriptingObject" event and get a reference to each of the objects as they are scripted.
        /// </summary>
        /// <param name="connectionString">The connection string for the database to script.</param>
        /// <param name="scriptingFolder">The directory in which to place the files.</param>
        /// <param name="createSubfolders">Indicates whether to create a folder for each type of object.</param>
        /// <param name="documentationDestinationFolder">The destination folder for the documentation objects.</param>
        void ScriptToFile(
            string connectionString,
            DirectoryInfo scriptingFolder,
            bool createSubfolders,
            DirectoryInfo documentationDestinationFolder);

        /// <summary>
        /// Script a connection and save the results in files.
        /// In addition to the script being saved in a file, it is also possible to handle
        /// the "CompleteScriptingObject" event and get a reference to each of the objects as they are scripted.
        /// Apply certain filters to the objects and/or object types.
        /// </summary>
        /// <param name="connectionString">The connection string for the database to script.</param>
        /// <param name="scriptingFolder">The directory in which to place the files.</param>
        /// <param name="createSubfolders">Indicates whether to create a folder for each type of object.</param>
        /// <param name="documentationDestinationFolder">The destination folder for the documentation objects.</param>
        /// <param name="typesToInclude">
        /// A specific list of object types to include in the scripting process.
        /// Pass an empty array or null to include all object types.
        /// </param>
        /// <param name="typesToExclude">
        /// A list of object types to exclude from the scripting specifically.
        /// Overrides the included object types if there is a conflict.
        /// Pass empty array or null not to for nothing to be excluded.
        /// </param>
        /// <param name="objectsToInclude">
        /// A specific list of objects to include in the scripting process.
        /// Pass an empty array or null to include all objects.
        /// </param>
        /// <param name="objectsToExclude">
        /// A list of object types to exclude from the scripting specifically.
        /// Overrides the included objects if there is a conflict.
        /// Pass empty array or null not to for nothing to be excluded.
        /// </param>
        void ScriptToFile(
            string connectionString,
            DirectoryInfo scriptingFolder,
            bool createSubfolders,
            DirectoryInfo documentationDestinationFolder,
            string[] typesToInclude,
            string[] typesToExclude,
            string[] objectsToInclude,
            string[] objectsToExclude);

        /// <summary>
        /// Script a connection and return a collection containing all the objects.
        /// In addition to the script being saved in the collection, it is also possible to handle
        /// the "CompleteScriptingObject" event and get a reference to each of the objects as they are scripted.
        /// </summary>
        /// <param name="connectionString">The connection string for the database to script.</param>
        /// <returns>The collection of objects.</returns>
        Collection<IDataStructureObject> ScriptToCollection(string connectionString);

        /// <summary>
        /// Script a connection and return a collection containing all the objects.
        /// In addition to the script being saved in the collection, it is also possible to handle
        /// the "CompleteScriptingObject" event and get a reference to each of the objects as they are scripted.
        /// Apply certain filters to the objects and/or object types.
        /// </summary>
        /// <param name="connectionString">The connection string for the database to script.</param>
        /// <param name="typesToInclude">
        /// A specific list of object types to include in the scripting process.
        /// Pass an empty array or null to include all object types.
        /// </param>
        /// <param name="typesToExclude">
        /// A list of object types to exclude from the scripting specifically.
        /// Overrides the included object types if there is a conflict.
        /// Pass empty array or null not to for nothing to be excluded.
        /// </param>
        /// <param name="objectsToInclude">
        /// A specific list of objects to include in the scripting process.
        /// Pass an empty array or null to include all objects.
        /// </param>
        /// <param name="objectsToExclude">
        /// A list of object types to exclude from the scripting specifically.
        /// Overrides the included objects if there is a conflict.
        /// Pass empty array or null not to for nothing to be excluded.
        /// </param>
        /// <returns>The collection of filtered objects.</returns>
        Collection<IDataStructureObject> ScriptToCollection(
            string connectionString,
            string[] typesToInclude,
            string[] typesToExclude,
            string[] objectsToInclude,
            string[] objectsToExclude);

        /// <summary>
        /// Script a connection and use the "CompleteScriptingObject" event to
        /// get a reference to each of the objects as they are scripted.
        /// </summary>
        /// <param name="connectionString">The connection string for the database to script.</param>
        void ScriptToCallback(string connectionString);

        /// <summary>
        /// Script a connection and use the "CompleteScriptingObject" event to
        /// get a reference to each of the objects as they are scripted.
        /// Apply certain filters to the objects and/or object types.
        /// </summary>
        /// <param name="connectionString">The connection string for the database to script.</param>
        /// <param name="typesToInclude">
        /// A specific list of object types to include in the scripting process.
        /// Pass an empty array or null to include all object types.
        /// </param>
        /// <param name="typesToExclude">
        /// A list of object types to exclude from the scripting specifically.
        /// Overrides the included object types if there is a conflict.
        /// Pass empty array or null not to for nothing to be excluded.
        /// </param>
        /// <param name="objectsToInclude">
        /// A specific list of objects to include in the scripting process.
        /// Pass an empty array or null to include all objects.
        /// </param>
        /// <param name="objectsToExclude">
        /// A list of object types to exclude from the scripting specifically.
        /// Overrides the included objects if there is a conflict.
        /// Pass empty array or null not to for nothing to be excluded.
        /// </param>
        void ScriptToCallback(
            string connectionString,
            string[] typesToInclude,
            string[] typesToExclude,
            string[] objectsToInclude,
            string[] objectsToExclude);
    }
}
